/*
*********************************************************************************************************
*                                                    LINUX-KERNEL
*                                        AllWinner Linux Platform Develop Kits
*                                                   Kernel Module
*
*                                    (c) Copyright 2006-2011, kevin.z China
*                                             All Rights Reserved
*
* File    : pm.h
* By      : kevin.z
* Version : v1.0
* Date    : 2011-5-27 14:08
* Descript: power manager
* Update  : date                auther      ver     notes
*********************************************************************************************************
*/
#ifndef __AW_PM_H__
#define __AW_PM_H__

#include "axp_depend.h"

#define BITMAP(bit) (0x1<<bit)

/**max device number of pmu*/
#define PMU_MAX_DEVS        2

/**
*@name PMU command
*@{
*/
#define AW_PMU_SET          0x10
#define AW_PMU_VALID        0x20
/**
*@}
*/

/*
* the wakeup source of main cpu: cpu0
*/
#define CPU0_WAKEUP_MSGBOX      (1<<0)  /* external interrupt, pmu event for ex.    */
#define CPU0_WAKEUP_KEY         (1<<1)  /* key event    */
#define CPU0_WAKEUP_EXINT	(1<<2)
#define CPU0_WAKEUP_IR		(1<<3)
#define CPU0_WAKEUP_ALARM	(1<<4)
#define CPU0_WAKEUP_USB		(1<<5)
#define CPU0_WAKEUP_TIMEOUT	(1<<6)
#define CPU0_WAKEUP_PIO		(1<<7)


//the wakeup source of assistant cpu: cpus
#define CPUS_WAKEUP_LOWBATT     (1<<12 )
#define CPUS_WAKEUP_USB         (1<<13 )
#define CPUS_WAKEUP_AC          (1<<14 )
#define CPUS_WAKEUP_ASCEND      (1<<15 )
#define CPUS_WAKEUP_DESCEND     (1<<16 )
#define CPUS_WAKEUP_SHORT_KEY   (1<<17 )
#define CPUS_WAKEUP_LONG_KEY    (1<<18 )
#define CPUS_WAKEUP_IR          (1<<19 )
#define CPUS_WAKEUP_ALM0        (1<<20)
#define CPUS_WAKEUP_ALM1        (1<<21)
#define CPUS_WAKEUP_TIMEOUT     (1<<22)
#define CPUS_WAKEUP_GPIO        (1<<23)
#define CPUS_WAKEUP_USBMOUSE    (1<<24)
#define CPUS_WAKEUP_LRADC       (1<<25)
//null for 1<<26
#define CPUS_WAKEUP_CODEC       (1<<27)
#define CPUS_WAKEUP_BAT_TEMP    (1<<28)
#define CPUS_WAKEUP_FULLBATT    (1<<29)
#define CPUS_WAKEUP_HMIC        (1<<30)
#define CPUS_WAKEUP_POWER_EXP   (1<<31)
#define CPUS_WAKEUP_KEY         (CPUS_WAKEUP_SHORT_KEY | CPUS_WAKEUP_LONG_KEY)

//for format all the wakeup gpio into one word.
#define GPIO_PL_MAX_NUM		    (11)    //0-11
#define GPIO_PM_MAX_NUM		    (11)    //0-11
#define GPIO_AXP_MAX_NUM	    (7)	    //0-7

#define WAKEUP_GPIO_PL(num)         (1 << (num))
#define WAKEUP_GPIO_PM(num)         (1 << (num + 12))
#define WAKEUP_GPIO_AXP(num)        (1 << (num + 24))
#define WAKEUP_GPIO_GROUP(group)    (1 << (group - 'A'))

#if defined(CONFIG_ARCH_SUN8IW6P1) || defined(CONFIG_ARCH_SUN8IW8P1)
#define IO_NUM (2)
#elif defined(CONFIG_ARCH_SUN9IW1P1)
#define PLL_NUM (12)
#define BUS_NUM (15)
#define IO_NUM (2)
#else
#define PLL_NUM (11)
#define BUS_NUM (6)
#define IO_NUM (2)
#endif

#if defined(CONFIG_ARCH_SUN9IW1P1)
typedef struct pll_para{
	int n;
	int p;
	int divi; /* input_div */
	int divo; /* output_div */
}pll_para_t;
#elif defined(CONFIG_ARCH_SUN8IW6P1) || defined(CONFIG_ARCH_SUN8IW8P1)
typedef struct pll_para{
	unsigned int factor1;
	unsigned int factor2;
	unsigned int factor3;
	unsigned int factor4;
}pll_para_t;
#else
typedef struct pll_para{
	unsigned int n;	//for a83, pll6, n
	unsigned int k; //		div1
	unsigned int m; //		div2
	unsigned int p;
}pll_para_t;
#endif

typedef struct bus_para{
	unsigned int src;
	unsigned int pre_div;
	unsigned int div_ratio;
	unsigned int n;
	unsigned int m;
}bus_para_t;

#if defined(CONFIG_ARCH_SUN8IW6P1) || defined(CONFIG_ARCH_SUN8IW8P1)
//for bitmap macro definition
#define PM_PLL_C0      (0)
#define PM_PLL_C1      (1)
#define PM_PLL_AUDIO   (2)
#define PM_PLL_VIDEO0  (3)
#define PM_PLL_VE      (4)
#define PM_PLL_DRAM    (5)
#define PM_PLL_PERIPH  (6)
#define PM_PLL_GPU	    (7)
#define PM_PLL_HSIC    (8)
#define PM_PLL_DE	    (9)
#define PM_PLL_VIDEO1  (10)
#define PLL_NUM (11)

#define BUS_C0      (0)
#define BUS_C1      (1)
#define BUS_AXI0    (2)
#define BUS_AXI1    (3)
#define BUS_AHB1    (4)
#define BUS_AHB2    (5)
#define BUS_APB1    (6)
#define BUS_APB2    (7)
#define BUS_NUM	    (8)

#define OSC_HOSC_BIT	    (3)
#define OSC_LOSC_BIT	    (2)
#define OSC_LDO1_BIT	    (1)
#define OSC_LDO0_BIT	    (0)

typedef enum clk_src
{
	CLK_SRC_NONE = 0x0, //invalid source clock id

	CLK_SRC_LOSC,   //LOSC, 33/50/67:32768Hz, 73:16MHz/512=31250
	CLK_SRC_IOSC,   //InternalOSC,  33/50/67:700KHZ, 73:16MHz
	CLK_SRC_HOSC,   //HOSC, 24MHZ clock
	CLK_SRC_AXI,    //AXI clock
	CLK_SRC_16M,    //16M for the backdoor

	CLK_SRC_PLL1,   //PLL1 clock
	CLK_SRC_PLL2,   //PLL2 clock
	CLK_SRC_PLL3,   //PLL3 clock
	CLK_SRC_PLL4,   //PLL4 clock
	CLK_SRC_PLL5,   //PLL5 clock
	CLK_SRC_PLL6,   //PLL6 clock
	CLK_SRC_PLL7,   //PLL7 clock
	CLK_SRC_PLL8,   //PLL8 clock
	CLK_SRC_PLL9,   //PLL9 clock
	CLK_SRC_PLL10,  //PLL10 clock
	CLK_SRC_PLL11,  //PLL10 clock

	CLK_SRC_CPUS,   //cpus clock
	CLK_SRC_C0,     //cluster0 clock
	CLK_SRC_C1,     //cluster1 clock
	CLK_SRC_AXI0,   //AXI0 clock
	CLK_SRC_AXI1,   //AXI0 clock
	CLK_SRC_AHB0,   //AHB0 clock
	CLK_SRC_AHB1,   //AHB1 clock
	CLK_SRC_AHB2,   //AHB2 clock
	CLK_SRC_APB0,   //APB0 clock
	CLK_SRC_APB1,   //APB1 clock
	CLK_SRC_APB2,   //APB2 clock
} clk_src_e;

typedef struct pwr_dm_state{
    /* 
     * for state bitmap: 
     * bitx = 1: keep state.
     * bitx = 0: mean close corresponding power src.
     */
    unsigned int state;	
    unsigned int sys_mask;	//bitx=1, the corresponding state is effect, 
				//otherwise, the corresponding power is in charge in device driver.
    
    // sys_mask&state		: bitx=1, mean the power is on, for the "on" state power, u need care about the voltage.;
    // ((~sys_mask)|state)		: bitx=0, mean the power is close;
    // pwr_dm_state bitmap
    
    // actually: we care about the pwr_dm voltage, 
    // such as: we want to keep the vdd_sys at 1.0v at standby period.
    //		we actually do not care how to do it.
    //		it can be sure that cpus can do it with the pmu's help.
    unsigned short volt[VCC_MAX_INDEX]; //unsigned short is 16bit width.  
}pwr_dm_state_t;

typedef struct dram_para{
    unsigned int selfresh_flag; //selfresh_flag must be compatible with vdd_sys pwr state.
    unsigned int crc_en;
    unsigned int crc_start;
    unsigned int crc_len;
}dram_para_t;

typedef struct cpus_clk_para{
    unsigned int cpus_id;
}cpus_para_t;

typedef struct io_state_config{
    unsigned int *paddr;
    unsigned int value_mask; //specify the effect bit.
    unsigned int value;
}io_state_config_t;

typedef struct soc_io_para{
    /*
     *	hold: mean before power off vdd_sys, whether hold gpio pad or not.
     *	this flag only effect: when vdd_sys is powered_off;
     *	this flag only affect hold&unhold operation.
     *	the recommended hold sequence is as follow: 
     *	backup_io_cfg -> cfg_io(enter_low_power_mode) -> hold -> assert vdd_sys_reset -> poweroff vdd_sys.
     *  the recommended unhold sequence is as follow: 
     *  poweron vdd_sys -> de_assert vdd_sys -> restore_io_cfg -> unhold.
     * */
    unsigned int hold_flag;

    
    /*
     * note: only specific bit mark by value_mask is effect.
     * IO_NUM: only uart and jtag needed care.
     * */
    io_state_config_t io_state[IO_NUM];
}soc_io_para_t;

typedef struct cpux_clk_para{
    /*
     * Hosc: losc: ldo1: ldo0
     * the osc bit map is as follow:
     * bit3: bit2: bit1:bit0
     * Hosc: losc: ldo1: ldo0
     */
    int osc_en;

    /*
     * for a83, pll bitmap as follow:
     * bit7:	    bit6:	bit5:	    bit4:	bit3:		bit2:		bit1:	    bit0
     * pll8(gpu): pll6(periph): pll5(dram): pll4(ve): pll3(video):	pll2(audio):	c1cpux:	    c0cpux
     *									pll11(video1):	pll10(de):  pll9(hsic)
     * */

    /* for disable bitmap:
     * bitx = 0: close
     * bitx = 1: do not care.
     */
    int init_pll_dis;
	 
    /* for enable bitmap:
     * bitx = 0: do not care.
     * bitx = 1: open
     */
    int exit_pll_en;

    /*
     * set corresponding bit if it's pll factors need to be set some value.
     */
    int pll_change;

    /*
     * fill in the enabled pll freq factor sequently. unit is khz pll6: 0x90041811
     * factor n/m/k/p already do the pretreatment of the minus one
     */
    pll_para_t pll_factor[PLL_NUM];

    /*
     * **********A31************
     * at a31 platform, the clk relationship is as follow:
     * pll1->cpu -> axi
     *	     -> atb/apb
     * ahb1 -> apb1
     * apb2
     * so, at a31, only cpu:ahb1:apb2 need be cared.
     *
     * *********A80************
     * at a83 platform, the clk relationship is as follow:
     * c1 -> axi1
     * c0 -> axi0
     * gtbus
     * ahb0
     * ahb1
     * ahb2
     * apb0
     * apb1
     * so, at a80, c1:c0:gtbus:ahb0:ahb1:ahb2:apb0:apb1 need be cared.
     *
     * *********A83************
     * at a83 platform, the clk relationship is as follow:
     * c1 -> axi1
     * c0 -> axi0
     * ahb1 -> apb1
     * apb2
     * ahb2
     * so, at a83, only c1:c0:ahb1:apb2:ahb2 need be cared.
     *
     * normally, only clk src need be cared.
     * the bus bitmap as follow:
     * for a83, bus_en:  
     * bit4: bit3: bit2: bit1: bit0
     * ahb2: apb2: ahb1: c1:   c0
     *
     * for a31, bus_en: 
     * bit2:bit1:bit0
     * cpu:ahb1:apb2
     *
     * for a80, bus_en: 
     * bit7: bit6:  bit5:  bit4: bit3: bit2: bit1: bit0
     * c1:   c0:    gtbus: ahb0: ahb1: ahb2: apb0: apb1
     */
    int bus_change;

    /*
     * bus_src: ahb1, apb2 src;
     * option:  pllx:axi:hosc:losc
     */
    bus_para_t bus_factor[BUS_NUM];

}cpux_clk_para_t;

typedef struct soc_pwr_dep{
    /*
     * id of scene_lock
     */
    unsigned long id;
    
    pwr_dm_state_t soc_pwr_dm_state;
    dram_para_t soc_dram_state; 
    soc_io_para_t soc_io_state;
    cpux_clk_para_t cpux_clk_state;

}soc_pwr_dep_t;

typedef struct extended_standby{
    /*
     * id of extended standby
     */
    unsigned long id;
    unsigned int pmu_id;	//for: 808 || 809+806 || 803 || 813
				//support 4 pmu: each pmu_id range is: 0-255;
				//pmu_id <--> pmu_name have directly mapping, u can get the pmu_name from sys_config.fex files.;
				//bitmap as follow:
				//pmu1: 0-7 bit; pmu2: 8-15 bit; pmu3: 16-23 bit; pmu4: 24-31 bit
				//

    unsigned int soc_id;        // a33, a80, a83,...,
                                // for compatible reason, different soc, each bit have different meaning.

    pwr_dm_state_t soc_pwr_dm_state;
    dram_para_t soc_dram_state; 
    soc_io_para_t soc_io_state;
    cpux_clk_para_t cpux_clk_state;
}extended_standby_t;

#else

typedef struct extended_standby{
	/*
	 * id of extended standby
	 */
	unsigned long id;
	/*
	 * clk tree para description as follow:
	 * vdd_dll : exdev : avcc : vcc_wifi : vcc_dram: vdd_sys : vdd_cpux : vdd_gpu : vcc_io : vdd_cpus
	 */
	int pwr_dm_en;	//bitx = 1, mean power on when sys is in standby state. otherwise, vice verse.

	/*
	 * Hosc: losc: ldo: ldo1
	 */
	int osc_en;

	/*
	 * pll_10: pll_9: pll_mipi: pll_8: pll_7: pll_6: pll_5: pll_4: pll_3: pll_2: pll_1
	 */
	int init_pll_dis;

	/*
	 * pll_10: pll_9: pll_mipi: pll_8: pll_7: pll_6: pll_5: pll_4: pll_3: pll_2: pll_1
	 */
	int exit_pll_en;

	/*
	 * set corresponding bit if it's pll factors need to be set some value.
	 * pll_10: pll_9: pll_mipi: pll_8: pll_7: pll_6: pll_5: pll_4: pll_3: pll_2: pll_1
	 */
	int pll_change;

	/*
	 * fill in the enabled pll freq factor sequently. unit is khz pll6: 0x90041811
	 * factor n/m/k/p already do the pretreatment of the minus one
	 */
	pll_para_t pll_factor[PLL_NUM];

	/*
	 * bus_en: cpu:axi:atb/apb:ahb1:apb1:apb2,
	 * normally, only clk src need be cared.
	 * so, at a31, only cpu:ahb1:apb2 need be cared.
	 * pll1->cpu -> axi
	 *	     -> atb/apb
	 * ahb1 -> apb1
	 * apb2
	 */
	int bus_change;

	/*
	 * bus_src: ahb1, apb2 src;
	 * option:  pllx:axi:hosc:losc
	 */
	bus_para_t bus_factor[BUS_NUM];
}extended_standby_t;
#endif

#define CPUS_ENABLE_POWER_EXP   (1<<31)
#define CPUS_WAKEUP_POWER_STA   (1<<1 )
#define CPUS_WAKEUP_POWER_CSM   (1<<0 )
typedef struct sst_power_info_para
{
	/*
	 * define for sun9iw1p1
	 * power_reg bit0 ~ 7 AXP_main REG10, bit 8~15 AXP_main REG12
	 * power_reg bit16~23 AXP_slav REG10, bit24~31 AXP_slav REG11
	 *
	 * AXP_main REG10: 0-off, 1-on
	 * bit7   bit6   bit5   bit4   bit3   bit2   bit1   bit0
	 * aldo2  aldo1  dcdc5  dcdc4  dcdc3  dcdc2  dcdc1  dc5ldo
	 *
	 * REG12: bit0~5:0-off, 1-on, bit6~7: 0-on, 1-off, dc1sw's power come from dcdc1
	 * bit7   bit6   bit5   bit4   bit3   bit2   bit1   bit0
	 * dc1sw  swout  aldo3  dldo2  dldo1  eldo3  eldo2  eldo1
	 *
	 * AXP_slave REG10: 0-off, 1-on. dcdc b&c is not used, ignore them.
	 * bit7   bit6   bit5   bit4   bit3   bit2   bit1   bit0
	 * aldo3  aldo2  aldo1  dcdce  dcdcd  dcdcc  dcdcb  dcdca
	 *
	 * AXP_slave REG11: 0-off, 1-on
	 * bit7   bit6   bit5   bit4   bit3   bit2   bit1   bit0
	 * swout  cldo3  cldo2  cldo1  bldo4  bldo3  bldo2  bldo1
	 */
	/*
	 * define for sun8iw5p1
	 * power_reg0 ~ 7 AXP_main REG10,  8~15 AXP_main REG12
	 * power_reg16~32 null
	 *
	 * AXP_main REG10: 0-off, 1-on
	 * bit7   bit6	 bit5   bit4   bit3   bit2   bit1   bit0
	 * aldo2  aldo1  dcdc5  dcdc4  dcdc3  dcdc2  dcdc1  dc5ldo
	 *
	 * REG12: 0-off, 1-on
	 * bit7   bit6   bit5   bit4   bit3   bit2   bit1   bit0
	 * dc1sw  dldo4  dldo3  dldo2  dldo1  eldo3  eldo2  eldo1
	 *
	 * REG13: bit16 aldo3, 0-off, 1-on
	 * REG90: bit17 gpio0/ldo, 0-off, 1-on
	 * REG92: bit18 gpio1/ldo, 0-off, 1-on
	 */
	unsigned int enable;		/* enable bit */
	unsigned int power_reg;		/* registers of power state should be */
	signed int system_power;	/* the max power of system, signed, power mabe negative when charge */
} sst_power_info_para_t;

typedef	struct super_standby_para
{
	unsigned long event;			//cpus wakeup event types
	unsigned long resume_code_src; 		//cpux resume code src
	unsigned long resume_code_length; 	//cpux resume code length
	unsigned long resume_entry; 		//cpux resume entry
	unsigned long timeout;			//wakeup after timeout seconds
	unsigned long gpio_enable_bitmap;
	unsigned long cpux_gpiog_bitmap;
	extended_standby_t *pextended_standby;
} super_standby_para_t;

typedef	struct normal_standby_para
{
	unsigned long event;		//cpus wakeup event types
	unsigned long timeout;		//wakeup after timeout seconds
	unsigned long gpio_enable_bitmap;
	unsigned long cpux_gpiog_bitmap;
	extended_standby_t *pextended_standby;
} normal_standby_para_t;


//define cpus wakeup src
#define CPUS_MEM_WAKEUP              (CPUS_WAKEUP_LOWBATT | CPUS_WAKEUP_USB | CPUS_WAKEUP_AC | \
						CPUS_WAKEUP_DESCEND | CPUS_WAKEUP_ASCEND | CPUS_WAKEUP_ALM0 | CPUS_WAKEUP_GPIO | CPUS_WAKEUP_IR)
#define CPUS_BOOTFAST_WAKEUP         (CPUS_WAKEUP_LOWBATT | CPUS_WAKEUP_LONG_KEY |CPUS_WAKEUP_ALM0|CPUS_WAKEUP_USB|CPUS_WAKEUP_AC )

/*used in normal standby*/
#ifdef CONFIG_ARCH_SUN8IW8
#define CPU0_MEM_WAKEUP              (CPU0_WAKEUP_MSGBOX | CPU0_WAKEUP_EXINT | CPU0_WAKEUP_PIO)
#else
#define CPU0_MEM_WAKEUP              (CPU0_WAKEUP_MSGBOX | CPU0_WAKEUP_EXINT)
#endif

#define CPU0_BOOTFAST_WAKEUP         (CPU0_WAKEUP_MSGBOX)


/**
*@brief struct of pmu device arg
*/
struct aw_pmu_arg{
    unsigned int  twi_port;		/**<twi port for pmu chip   */
    unsigned char dev_addr;		/**<address of pmu device   */
    unsigned int  soc_power_tree[VCC_MAX_INDEX];     /* power tree struct point */
};


/**
*@brief struct of standby
*/
struct aw_standby_para{
	unsigned int event;		/**<event type for system wakeup    */
	unsigned int axp_event;		/**<axp event type for system wakeup    */
	unsigned int debug_mask;	/* debug mask */
	signed int   timeout;		/**<time to power off system from now, based on second */
	unsigned long gpio_enable_bitmap;
	unsigned long cpux_gpiog_bitmap;
	extended_standby_t *pextended_standby;
};


/**
*@brief struct of power management info
*/
struct aw_pm_info{
    struct aw_standby_para		standby_para;   /* standby parameter            */
    struct aw_pmu_arg			pmu_arg;        /**<args used by main function  */
};

typedef struct sst_dram_info
{
	unsigned int dram_crc_enable;
	unsigned int *dram_crc_src;
	unsigned int dram_crc_len;
	unsigned int dram_crc_error;
	unsigned int dram_crc_total_count;
	unsigned int dram_crc_error_count;
} sst_dram_info_t;

typedef struct standby_info_para
{
	sst_power_info_para_t power_state; /* size 3W=12B */
	sst_dram_info_t dram_state; /*size 6W=24B */
} standby_info_para_t;

typedef enum event_cpu_id
{
    CPUS_ID,
    CPU0_ID,
} event_cpu_id_e;

extern unsigned int parse_wakeup_gpio_group_map(char *s, unsigned int size, unsigned int gpio_map);

extern unsigned int parse_wakeup_event(char *s, unsigned int size, unsigned int event, event_cpu_id_e cpu_id);

extern unsigned int parse_wakeup_gpio_map(char *s, unsigned int size, unsigned int gpio_map);

extern unsigned int show_gpio_config(char *s, unsigned int size);

#endif /* __AW_PM_H__ */

